#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
using namespace std;

// 使用多线程去打印1~100的数，线程A打印奇数，线程B打印偶数
int main()
{
    mutex lock;
    condition_variable cv1,cv2;
    int nums = 100;
    thread t1([&]()
    {
        while(nums >= 0)
        {
            unique_lock<mutex> ulock(lock);
            // if(nums%2 == 0)//只适合单cp模型,会导致误唤醒错误
            // {
            //     cv1.wait(ulock);          
            // }
            /*正确写法*/
            //while (!pred()) wait(lck);
            /*不满足后面的条件就一直锁住*/
            cv1.wait(ulock,[&nums](){return (nums%2 != 0)||(nums == 0);});
            /*
            为什么不写nums == 0会阻塞？
            这个错误是因为，但我用c线程去唤醒p线程的时候，
            nums不成立wait中lambda的条件，
            在lambda加上nums==0这个条件即可
            */
            if(nums == 0)
            {
                cv2.notify_one();
                break;
            }
            --nums;
            cout<<this_thread::get_id()<<" print: "<<nums<<endl;
            cv2.notify_one();
            
        } 
    });
    
    thread t2([&]()
    {
        while(nums >= 0)
        {
            unique_lock<mutex> ulock(lock);
            
            // if(nums % 2 != 0)
            // {
            //     cv2.wait(ulock);          
            // }
            cv2.wait(ulock,[&nums](){return (nums%2 == 0)||(nums == 0);});
            /*
                为什么这里条件写在上面条件的下面？
                因为唤醒后的线程会在休眠的位置继续执行！！
            */ 
            if(nums == 0)
            {
                cv1.notify_one();
                break;
            }
            --nums;
            cout<<this_thread::get_id()<<" print: "<<nums<<endl;
            cv1.notify_one();
        } 
    });

    t1.join();
    t2.join();
    return 0;
}